package com.sinog.biz.service.business.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sinog.biz.config.ThreadPoolConfig;
import com.sinog.biz.mapper.havexml.AbAnzhiMapper;
import com.sinog.biz.mapper.havexml.AbBangfuMapper;
import com.sinog.biz.mapper.havexml.AbCunJiandingMapper;
import com.sinog.biz.mapper.havexml.AbJiuMapper;
import com.sinog.biz.mapper.havexml.AbLieguanMapper;
import com.sinog.biz.mapper.havexml.AbPrisonerMapper;
import com.sinog.biz.mapper.havexml.PrisaveTempMapper;
import com.sinog.biz.mapper.havexml.PrisonerFxExcelTempMapper;
import com.sinog.biz.mapper.havexml.PrisonerFxMapper;
import com.sinog.biz.mapper.havexml.PrisonerMainExcelTempMapper;
import com.sinog.biz.mapper.havexml.PrisonerMainMapper;
import com.sinog.biz.mapper.havexml.PrisonerSrExcelTempMapper;
import com.sinog.biz.mapper.havexml.PrisonerSrMapper;
import com.sinog.biz.mapper.havexml.PrisonerXjxxMapper;
import com.sinog.biz.mapper.havexml.PrisonerZnExcelTempMapper;
import com.sinog.biz.mapper.havexml.PrisonerZnMapper;
import com.sinog.biz.mapper.havexml.SystemCodeMapper;
import com.sinog.biz.service.business.PrisonerMainBlService;
import com.sinog.biz.service.business.PrisonerMainService;
import com.sinog.biz.service.business.SentenceService;
import com.sinog.biz.service.business.SocialRelationsService;
import com.sinog.biz.service.serviceimpl.AbXiaozuService;
import com.sinog.core.domain.AbAnzhiResultVo;
import com.sinog.core.domain.AbBangfuResultVo;
import com.sinog.core.domain.AbCunJiandingResultVo;
import com.sinog.core.domain.AbJiuResultVo;
import com.sinog.core.domain.AbLieguan;
import com.sinog.core.domain.AbPrisonersResultVo;
import com.sinog.core.domain.AbXiaozuResultVo;
import com.sinog.core.domain.PrisaveTemp;
import com.sinog.core.domain.PrisonerFx;
import com.sinog.core.domain.PrisonerFxExcelTemp;
import com.sinog.core.domain.PrisonerMain;
import com.sinog.core.domain.PrisonerMainExcelTemp;
import com.sinog.core.domain.PrisonerSr;
import com.sinog.core.domain.PrisonerSrExcelTemp;
import com.sinog.core.domain.PrisonerXjxx;
import com.sinog.core.domain.PrisonerZn;
import com.sinog.core.domain.PrisonerZnExcelTemp;
import com.sinog.core.domain.SystemCode;
import com.sinog.core.model.UserDTO;
import com.sinog.core.util.JsonUtil;
import com.sinog.core.util.MapUtil;
import com.sinog.core.util.PageReturnUtil;
import com.sinog.core.utilbean.Constants;
import com.sinog.core.utilbean.Result;
import com.sinog.core.utilbean.ReturnCode;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CountDownLatch;

/**
 * @desc 安置帮教管理 - 人员信息补录 - 信息录入
 * @author -
 * @date 2020-01-19-14:02
 */
@Service
@Slf4j
public class PrisonerMainBlServiceImpl extends ServiceImpl<PrisonerMainMapper,PrisonerMain> implements PrisonerMainBlService {

    @Resource
    private SystemCodeMapper systemCodeMapper;
    @Resource
    private PrisonerMainMapper prisonerMainMapper;
    @Resource
    private PrisonerMainExcelTempMapper prisonerMainExcelTempMapper;
    @Resource
    private PrisonerXjxxMapper prisonerXjxxMapper;
    @Resource
    private AbXiaozuService abXiaozuService;
    @Resource
    private PrisaveTempMapper prisaveTempMapper;
    @Resource
    private PrisonerFxMapper prisonerFxMapper;
    @Resource
    private PrisonerFxExcelTempMapper prisonerFxExcelTempMapper;
    @Resource
    private AbPrisonerMapper abPrisonerMapper;
    @Resource
    private PrisonerSrMapper prisonerSrMapper;
    @Resource
    private PrisonerSrExcelTempMapper prisonerSrExcelTempMapper;
    @Resource
    private PrisonerZnMapper prisonerZnMapper;
    @Resource
    private PrisonerZnExcelTempMapper prisonerZnExcelTempMapper;
    @Resource
    private AbAnzhiMapper abAnzhiMapper;
    @Resource
    private AbJiuMapper abJiuMapper;
    @Resource
    private AbBangfuMapper abBangfuMapper;
    @Resource
    private AbCunJiandingMapper abCunJiandingMapper;
    @Resource
    private AbLieguanMapper abLieguanMapper;
    @Resource
    private PrisonerMainService prisonerMainService;
    @Resource
    private SentenceService sentenceService;
    @Resource
    private SocialRelationsService socialRelationsService;
    @Autowired
    private ThreadPoolConfig threadPoolConfig;

    /**
     * 安置帮教管理 - 人员信息补录 - 信息补录 - 列表
     * @param pageIndex 起始页
     * @param pageSize 止页
     * @param paramMap 查询条件
     * @return String
     */
    @Override
    public String getBlInmatesList(Integer pageIndex,Integer pageSize,Map<String,Object> paramMap) {
        //参数转换
        MapUtil.requestConversionToMap(paramMap);
        Page<Map<String,String>> page = new Page<>(pageIndex + 1,pageSize);
        page = page.setRecords(prisonerMainMapper.getBlInmatesList(page,paramMap));
        return PageReturnUtil.pageReturn(page);
    }

    /**
     * 根据司法所/司法局，回显一个户籍地
     * @param level level
     * @param departId departId
     * @return Result
     */
    @Override
    public Result getHuJi(String level,String departId) {
        List<SystemCode> systemCodes = new ArrayList<>(16);
        List<SystemCode> codeList = findAdminCodeById(departId,systemCodes);
        Collections.reverse(codeList);
        return Result.success(codeList);
    }

    /**
     * 描述
     * @param priNum priNum
     * @return String
     */
    @Override
    public String findTuJing(String priNum) {
        return prisonerXjxxMapper.findTuJing(priNum);
    }

    /**
     * 安置帮教管理 - 人员信息补录 - 信息补录 - 批量删除
     * @param priNums priNums
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void removeBaseInfoByPriNums(List<String> priNums){
        //1、批量删除main表
        prisonerMainMapper.delete(new QueryWrapper<PrisonerMain>().in("pri_num", priNums));
       //2、再删除ab_prisoners表
        abPrisonerMapper.delete(new QueryWrapper<AbPrisonersResultVo>().in("pri_num", priNums));
        //3、如果服刑信息添加了，就删除
        prisonerFxMapper.delete(new QueryWrapper<PrisonerFx>().in("pri_num", priNums));
        //4、如果有子女,社会关系信息，就删除
        prisonerSrMapper.delete(new QueryWrapper<PrisonerSr>().in("pri_num", priNums));
        //5、如果有未成年就删除
        prisonerZnMapper.delete(new QueryWrapper<PrisonerZn>().in("pri_num", priNums));
        //6、删除衔接表
        prisonerXjxxMapper.delete(new QueryWrapper<PrisonerXjxx>().in("pri_num",priNums));
        //7、删除小组表
        abXiaozuService.remove(new QueryWrapper<AbXiaozuResultVo>().in("pri_num",priNums));
        //8、如果安置了，需要删除安置表
        abAnzhiMapper.delete(new QueryWrapper<AbAnzhiResultVo>().in("pri_num",priNums));
        //9、如果救助了，需要删除求助表
        abJiuMapper.delete(new QueryWrapper<AbJiuResultVo>().in("pri_num",priNums));
        //10、如果帮扶了，就删除帮扶表
        abBangfuMapper.delete(new QueryWrapper<AbBangfuResultVo>().in("pri_num",priNums));
        //11、如果参与年度坚定了，就删除鉴定表
        abCunJiandingMapper.delete(new QueryWrapper<AbCunJiandingResultVo>().in("pri_num",priNums));
        //12、如果在双列管里头，就删除双列管
        abLieguanMapper.delete(new QueryWrapper<AbLieguan>().in("pri_num",priNums));
        //13、删除中间表
        prisaveTempMapper.delete(new QueryWrapper<PrisaveTemp>().in("pri_num",priNums));
    }

    /**
     * 安置帮教管理 - 人员信息补录 - 信息补录 - 删除按钮
     * @param priNum 服刑人员编号
     * @return int
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int removeBaseInfoByPriNum(String priNum) {
        int num1;
        int num2;
        int num3 = 0;
        int num4 = 0;
        int num5 = 0;
        int num6;
        int num8 = 0;
        int num9 = 0;
        int num10 = 0;
        int num11 = 0;
        int num12 = 0;
        int num13;
        //1、先删除main表
        num1 = prisonerMainMapper.delete(new QueryWrapper<PrisonerMain>().eq(Constants.StrFinalValue.PRINUM, priNum));
        //2、再删除ab_prisoners表
        num2 = abPrisonerMapper.deleteByPriNum(priNum);
        //3、如果服刑信息添加了，就删除
        if(prisonerFxMapper.selectCount(new QueryWrapper<PrisonerFx>().eq(Constants.StrFinalValue.PRINUM,priNum)) > 0) {
            num3 = prisonerFxMapper.delete(new QueryWrapper<PrisonerFx>().eq(Constants.StrFinalValue.PRINUM, priNum));
        }
        //4、如果有子女,社会关系信息，就删除
        if(prisonerSrMapper.selectCount(new QueryWrapper<PrisonerSr>().eq(Constants.StrFinalValue.PRINUM,priNum)) > 0) {
            num4 = prisonerSrMapper.delete(new QueryWrapper<PrisonerSr>().eq(Constants.StrFinalValue.PRINUM,priNum));
        }
        //5、如果有未成年就删除
        if(prisonerZnMapper.selectCount(new QueryWrapper<PrisonerZn>().eq(Constants.StrFinalValue.PRINUM,priNum)) > 0) {
            num5 = prisonerZnMapper.delete(new QueryWrapper<PrisonerZn>().eq(Constants.StrFinalValue.PRINUM,priNum));
        }
        //6、删除衔接表
        num6 = prisonerXjxxMapper.deleteXjxxByPriNum(priNum);
        //7、删除小组表
        abXiaozuService.remove(new QueryWrapper<AbXiaozuResultVo>().eq(Constants.StrFinalValue.PRINUM, priNum));
        //8、如果安置了，需要删除安置表
        if(abAnzhiMapper.selectCount(new QueryWrapper<AbAnzhiResultVo>().eq(Constants.StrFinalValue.PRINUM,priNum)) > 0) {
            num8 = abAnzhiMapper.delete(new QueryWrapper<AbAnzhiResultVo>().eq(Constants.StrFinalValue.PRINUM,priNum));
        }
        //9、如果救助了，就删除
        if(abJiuMapper.selectCount(new QueryWrapper<AbJiuResultVo>().eq(Constants.StrFinalValue.PRINUM,priNum)) > 0) {
            num9 = abJiuMapper.delete(new QueryWrapper<AbJiuResultVo>().eq(Constants.StrFinalValue.PRINUM,priNum));
        }
        //10、如果帮扶了，就删除
        if(abBangfuMapper.selectCount(new QueryWrapper<AbBangfuResultVo>().eq(Constants.StrFinalValue.PRINUM,priNum)) > 0) {
            num10 = abBangfuMapper.delete(new QueryWrapper<AbBangfuResultVo>().eq(Constants.StrFinalValue.PRINUM,priNum));
        }
        //11、如果参与年度坚定了，就删除
        if(abCunJiandingMapper.selectCount(new QueryWrapper<AbCunJiandingResultVo>().eq(Constants.StrFinalValue.PRINUM,priNum)) > 0) {
            num11 = abCunJiandingMapper.delete(new QueryWrapper<AbCunJiandingResultVo>().eq(Constants.StrFinalValue.PRINUM,priNum));
        }
        //12、如果在双列管里头，就删除
        if(abLieguanMapper.selectCount(new QueryWrapper<AbLieguan>().eq(Constants.StrFinalValue.PRINUM,priNum)) > 0) {
            num12 = abLieguanMapper.delete(new QueryWrapper<AbLieguan>().eq(Constants.StrFinalValue.PRINUM,priNum));
        }
        //13、删除中间表
        num13 = prisaveTempMapper.delete(new QueryWrapper<PrisaveTemp>().eq(Constants.StrFinalValue.PRINUM,priNum));
        return Math.max((num1 + num2 + num3 + num4 + num5 + num6 + num8 + num9 + num10 + num11 + num12 + num13),0);
    }

    /**
     * 描述
     * @param priNum priNum
     * @return int
     */
    @Override
    public int getFxByPriNum(String priNum) {
        return prisonerFxMapper.selectCount(new QueryWrapper<PrisonerFx>().eq("pri_num",priNum));
    }

    /**
     * 描述
     * @param priNum priNum
     * @return PrisonerMain
     */
    @Override
    public PrisonerMain getPrisonerPstate(String priNum) {
        QueryWrapper<PrisonerMain> wrapper = new QueryWrapper<>();
        return prisonerMainMapper.selectOne(wrapper.eq("pri_num",priNum));
    }

    /**
     * 查询该单位全部可以保存的数据
     * @param departid departid
     * @param user user
     * @return Result
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result selectMainExcels(String departid,UserDTO user) {
        //1、查询缓存表中当前用户的可保存数据
        //1.1、定义model条件
        QueryWrapper<PrisonerMainExcelTemp> wrapperMain = new QueryWrapper<>();
        QueryWrapper<PrisonerFxExcelTemp> wrapperFx = new QueryWrapper<>();
        QueryWrapper<PrisonerSrExcelTemp> wrapperSr = new QueryWrapper<>();
        QueryWrapper<PrisonerZnExcelTemp> wrapperZn = new QueryWrapper<>();
        //1.2、查询主表缓存表
        List<PrisonerMainExcelTemp> prisonerMainExcelTemps = prisonerMainExcelTempMapper.selectList(wrapperMain.eq("pdanwei",departid)
                                                                                                               .eq("success_flag",Constants.NumberStr.NUM_STR_ZERO)
                                                                                                                .eq("del_flag",Constants.NumberStr.NUM_STR_ZERO));
        if(Constants.Number.NUM_ZERO == prisonerMainExcelTemps.size()) {
            return Result.failure(ReturnCode.TEMPLATE_DATA_NO_IMPORT);
        }
        //1.3、取出组装主表缓存表的犯罪编号
        List<String> prinums = new ArrayList<>(16);
        for(PrisonerMainExcelTemp prisonerMainExcelTemp : prisonerMainExcelTemps) {
            String priNum = prisonerMainExcelTemp.getPriNum();
            prinums.add(priNum);
        }
        //1.4、查询服刑表缓存表、社会关系缓存表、子女缓存表
        List<PrisonerFxExcelTemp> prisonerFxExcelTemps = prisonerFxExcelTempMapper.selectList(wrapperFx.in("pri_num",prinums));
        List<PrisonerSrExcelTemp> prisonerSrExcelTemps = prisonerSrExcelTempMapper.selectList(wrapperSr.in("pri_num",prinums));
        List<PrisonerZnExcelTemp> prisonerZnExcelTemps = prisonerZnExcelTempMapper.selectList(wrapperZn.in("pri_num",prinums));
        //2、把上面四张缓存表数据分别组装后存储到真实业务表
        //2.1、组装主表缓存表并入真实库主表
        CountDownLatch maincCount = new CountDownLatch(prisonerMainExcelTemps.size());
        for(PrisonerMainExcelTemp prisonerMainExcelTemp : prisonerMainExcelTemps) {
            threadPoolConfig.taskExecutor().execute(() -> {
                if(Constants.OrgLevel.LEVEL_SJZX.equals(user.getLevel())){
                    prisonerMainExcelTemp.setPstate(Constants.InputEspecially.INPUT_SJ_EXCEL);
                } else if(Constants.OrgLevel.LEVEL_KSS.equals(user.getLevel())) {
                    prisonerMainExcelTemp.setPstate(Constants.InputEspecially.INPUT_KSS_EXCEL);
                } else if(Constants.OrgLevel.LEVEL_JY.equals(user.getLevel())){
                    prisonerMainExcelTemp.setPstate(Constants.InputEspecially.INPUT_JY_EXCEL);
                }
                String oldPriNum = prisonerMainExcelTemp.getPriNum();
                prisonerMainExcelTemp.setPriNum(null);
                String s = JsonUtil.toText(prisonerMainExcelTemp);
                Result result = prisonerMainService.saveBaseInfo(s,user,Constants.NumberStr.NUM_STR_ZERO);
                String newPriNum;
                if(Constants.Number.NUM_ONE.equals(result.getCode())){
                    Map<String,String> data = (Map<String,String>)result.getData();
                    newPriNum = data.get("priNum");
                    prisonerMainExcelTemp.setSuccessFlag(Constants.NumberStr.NUM_STR_TWO);
                    prisonerMainExcelTemp.setPriNum(oldPriNum);
                    prisonerMainExcelTemp.setMainPrinum(newPriNum);
                    prisonerMainExcelTemp.insertOrUpdate();
                    if(StringUtils.isNotBlank(newPriNum)){
                        for(PrisonerFxExcelTemp prisonerFxExcelTemp : prisonerFxExcelTemps) {
                            if(prisonerFxExcelTemp.getPriNum().equals(oldPriNum)){
                                prisonerFxExcelTemp.setPriNum(newPriNum);
                                String s1 = JsonUtil.toText(prisonerFxExcelTemp);
                                sentenceService.saveSentenceInfo(s1,user);
                            }
                        }
                        for(PrisonerSrExcelTemp prisonerSrExcelTemp : prisonerSrExcelTemps) {
                            if(prisonerSrExcelTemp.getPriNum().equals(oldPriNum)){
                                prisonerSrExcelTemp.setPriNum(newPriNum);
                                if(prisonerSrExcelTemp.getSrIdtype() != null) {
                                    prisonerSrExcelTemp.setIdType(prisonerSrExcelTemp.getSrIdtype());
                                }
                                String s2 = JsonUtil.toText(prisonerSrExcelTemp);
                                socialRelationsService.saveSrInfo(s2,user);
                            }
                        }
                        for(PrisonerZnExcelTemp prisonerZnExcelTemp : prisonerZnExcelTemps) {
                            if(prisonerZnExcelTemp.getPriNum().equals(oldPriNum)){
                                prisonerZnExcelTemp.setPriNum(newPriNum);
                                if(prisonerZnExcelTemp.getZnIdtype() != null) {
                                    prisonerZnExcelTemp.setIdType(prisonerZnExcelTemp.getZnIdtype());
                                }
                                String s3 = JsonUtil.toText(prisonerZnExcelTemp);
                                socialRelationsService.saveNoAdult(s3,user);
                            }
                        }
                    }
                } else {
                    prisonerMainExcelTemp.setPriNum(oldPriNum);
                    prisonerMainExcelTemp.setSuccessFlag("3");
                    prisonerMainExcelTemp.setErrMessage(result.getMessage());
                    prisonerMainExcelTemp.insertOrUpdate();
                }
                maincCount.countDown();
            });
        }
        if(prisonerMainExcelTemps.size() > 500) {
            return Result.failure(5000,"由于保存条数超过500，已提交后台保存，稍后查看！",null);
        }
        try {
            maincCount.await();
        } catch(InterruptedException e) {
            e.printStackTrace();
        }
        return Result.success();
    }

    /**
     * 查询主表缓存表
     * @param departid departid
     * @return Result
     */
    @Override
    public Result checkMainExcelImportData(String departid) {
        QueryWrapper<PrisonerMainExcelTemp> wrapperMain = new QueryWrapper<>();
        //查询主表缓存表
        List<PrisonerMainExcelTemp> prisonerMainExcelTemps = prisonerMainExcelTempMapper.selectList(wrapperMain.eq("pdanwei",departid)
                                                                                                               .eq("success_flag","0")
                                                                                                               .eq("del_flag","0"));
        if(Constants.Number.NUM_ZERO == prisonerMainExcelTemps.size()) {
            return Result.failure(ReturnCode.TEMPLATE_DATA_NO_IMPORT);
        }
        return Result.success();
    }

    /**
     * 描述
     * @param date date
     * @return List<Map<String,String>>
     */
    @Override
    public List<Map<String,String>> getUuidList(String date) {
        return prisonerMainExcelTempMapper.getUuidList(date);
    }

    /**
     * 根据司法所/区县司法局的街道编码/区县编码，查询出整个省/市/区县/街道
     * @param id id
     * @param list list
     * @return List<SystemCode>
     */
    private List<SystemCode> findAdminCodeById(String id,List<SystemCode> list) {
        SystemCode systemCode = systemCodeMapper.getByCode(Constants.CodeType.CODE_ZHRMGHG_XZQH_DM,id);
        list.add(systemCode);
        if(!Constants.NumberStr.NUM_STR_FU_ONE.equals(systemCode.getPcodeId())) {
            return findAdminCodeById(systemCode.getPcodeId(),list);
        }
        return list;
    }
}